package ops

import (
	"errors"
	"time"

	commonConstnt "algo-sdk-go/common/constant"
	"algo-sdk-go/common/tools"
	"algo-sdk-go/framework/middleware/db/mongodb/dbops"
	"algo-sdk-go/project/matchmaking/adapter/po"
	"algo-sdk-go/project/matchmaking/common/constant"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

func MatePreferenceValid(matePreference *po.MatePreference) dbops.ErrFunc {
	return func() error {
		if matePreference == nil || matePreference.UserNum == 0 {
			return errors.New("用户择偶数据不合法")
		}
		return nil
	}
}

func UserProfileValid(matePreference *po.UserProfile) dbops.ErrFunc {
	return func() error {
		if matePreference == nil || matePreference.UserNum == 0 {
			return errors.New("用户数据不合法")
		}
		return nil
	}
}

func WithUserNumsRemoveZero(ids []int, dbName string) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		ids = tools.UniqueAndFilter(ids, tools.IntUnique, tools.IntNotZero)
		if len(ids) != 0 {
			f.Arr = append(f.Arr, bson.M{dbName: bson.M{commonConstnt.DBIn: ids}})
		}
	}
}
func WithUserNum(id int, dbName string) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if id != 0 {
			f.Arr = append(f.Arr, bson.M{dbName: id})
		}
	}
}
func WithGender(gender string) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if gender != "" {
			f.Arr = append(f.Arr, bson.M{constant.DBGender: gender})
		}
	}
}
func WithAgeRange(ageRange AgeRange) dbops.FilterFunc {
	return dbops.WithRange(constant.DBAge, ageRange.MinAge, ageRange.MaxAge) // 1, 100
}
func WithHeightRange(heightRange HeightRange) dbops.FilterFunc {
	return dbops.WithRange(constant.DBHeight, heightRange.MinHeight, heightRange.MaxHeight) //1, 320
}
func WithWeightRange(weightRange WeightRange) dbops.FilterFunc {
	return dbops.WithRange(constant.DBWeight, weightRange.MinWeight, weightRange.MaxWeight) //1, 400
}
func WithIncomeRange(incomeRange IncomeRange) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if incomeRange.MinIncome > 0.01 {
			f.Arr = append(f.Arr, bson.M{constant.DBIncome: bson.M{commonConstnt.DBGte: incomeRange.MinIncome}})
		}
		if incomeRange.MaxIncome > 0.01 && incomeRange.MaxIncome < 1000000000 {
			f.Arr = append(f.Arr, bson.M{constant.DBIncome: bson.M{commonConstnt.DBLte: incomeRange.MaxIncome}})
		}
	}
}
func WithEducationRange(educationRange EducationRange) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if educationRange.MinEducation.Level() != 0 {
			f.Arr = append(f.Arr, bson.M{constant.DBEducationLevel: bson.M{commonConstnt.DBGte: educationRange.MinEducation.Level()}})
		}
		if educationRange.MaxEducation.Level() != 0 {
			f.Arr = append(f.Arr, bson.M{constant.DBEducationLevel: bson.M{commonConstnt.DBLte: educationRange.MaxEducation.Level()}})
		}
	}
}

func WithMaritalStatus(maritalStatus string) dbops.FilterFunc {
	return dbops.WithStringValue(constant.DBMaritalStatus, maritalStatus)
}

func WithNearestTime() dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		f.Arr = append(f.Arr, bson.M{constant.DBRecommendDate: bson.M{commonConstnt.DBGte: time.Now().AddDate(0, 0, 0)}})
	}
}

func ParentsRetirement(has bool) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if has {
			f.Arr = append(f.Arr, bson.M{commonConstnt.DBOr: []bson.M{
				{
					constant.DBFatherDetail: bson.M{
						commonConstnt.DBRegex: primitive.Regex{Pattern: ".*" + constant.Retirement + ".*", Options: commonConstnt.DBI},
					},
					constant.DBMotherDetail: bson.M{
						commonConstnt.DBRegex: primitive.Regex{Pattern: ".*" + constant.Retirement + ".*", Options: commonConstnt.DBI},
					},
				},
			}})
		}
	}
}
func WithoutDelete() dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		f.Arr = append(f.Arr, bson.M{constant.DBIsDeleted: false})
	}
}
func WithMinEducation(minEducation int) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if minEducation > 0 {
			f.Arr = append(f.Arr, bson.M{constant.DBEducationLevel: bson.M{commonConstnt.DBGte: minEducation}})
		}
	}
}

// TODO
func ParentsIsStateMember(has bool) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if has {
			f.Arr = append(f.Arr, bson.M{commonConstnt.DBOr: []bson.M{
				{
					constant.DBFatherDetail: bson.M{
						commonConstnt.DBRegex: primitive.Regex{Pattern: ".*" + constant.StateMember + ".*", Options: commonConstnt.DBI},
					},
					constant.DBMotherDetail: bson.M{
						commonConstnt.DBRegex: primitive.Regex{Pattern: ".*" + constant.StateMember + ".*", Options: commonConstnt.DBI},
					},
				},
			}})
		}
	}
}
func ParentsFreezeSearch(fuzzyWords []string) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		for _, fuzzyWord := range fuzzyWords {
			f.Arr = append(f.Arr,
				bson.M{fuzzyWord: bson.M{"$regex": primitive.Regex{Pattern: ".*" + constant.DBFatherDetail + ".*", Options: commonConstnt.DBI}}},
			)
		}
	}
}
func ParentsHasPension(has bool) dbops.FilterFunc {
	return func(f *dbops.FilterArr) {
		if has {
			f.Arr = append(f.Arr, bson.M{commonConstnt.DBOr: []bson.M{
				{
					constant.DBFatherDetail: bson.M{
						commonConstnt.DBRegex: primitive.Regex{Pattern: ".*" + constant.HasPension + ".*", Options: commonConstnt.DBI},
					},
					constant.DBMotherDetail: bson.M{
						commonConstnt.DBRegex: primitive.Regex{Pattern: ".*" + constant.HasPension + ".*", Options: commonConstnt.DBI},
					},
				},
			}})
		}
	}
}
